﻿using System;
using System.ComponentModel;
using RaytracerLib.MathLib;

namespace Raytracer.PropertyGridDecorators
{
    public class Matrix3Properties
    {
        public readonly Action<Matrix3> Setter;
        public readonly Func<Matrix3> Getter;

        public Matrix3Properties(Func<Matrix3> a_getter, Action<Matrix3> a_setter)
        {
            Getter = a_getter;
            Setter = a_setter;
        }

        public double[] ToArray()
        {
            return new double[]
            {
                Getter().M11, Getter().M12, Getter().M13,
                Getter().M21, Getter().M22, Getter().M23,
                Getter().M31, Getter().M32, Getter().M33,
            };
        }

        public double this[int a_index]
        {
            get
            {
                return ToArray()[a_index];
            }
            set
            {
                var ar = ToArray();
                ar[a_index] = value;
                Setter(new Matrix3(ar));
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M11
        {
            get
            {
                return this[0];
            }
            set
            {
                this[0] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M12
        {
            get
            {
                return this[1];
            }
            set
            {
                this[1] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M13
        {
            get
            {
                return this[2];
            }
            set
            {
                this[2] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M21
        {
            get
            {
                return this[3];
            }
            set
            {
                this[3] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M22
        {
            get
            {
                return this[4];
            }
            set
            {
                this[4] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M23
        {
            get
            {
                return this[5];
            }
            set
            {
                this[5] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M31
        {
            get
            {
                return this[6];
            }
            set
            {
                this[6] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M32
        {
            get
            {
                return this[7];
            }
            set
            {
                this[7] = value;
            }
        }

        [TypeConverter(typeof(DoubleConverter))]
        public double M33
        {
            get
            {
                return this[8];
            }
            set
            {
                this[8] = value;
            }
        }

        [TypeConverter(typeof(Vector2Converter))]
        public Vector2Properties Col1
        {
            get
            {
                return new Vector2Properties(
                    () => Getter().Col1,
                    (v) => Setter(Getter().SetCol1(v)));
            }
            set
            {
                Setter(Getter().SetCol1(value.ToVector2()));
            }
        }

        [TypeConverter(typeof(Vector2Converter))]
        public Vector2Properties Col2
        {
            get
            {
                return new Vector2Properties(
                    () => Getter().Col2,
                    (v) => Setter(Getter().SetCol2(v)));
            }
            set
            {
                Setter(Getter().SetCol2(value.ToVector2()));
            }
        }

        [TypeConverter(typeof(Vector2Converter))]
        public Vector2Properties Col3
        {
            get
            {
                return new Vector2Properties(
                    () => Getter().Col3,
                    (v) => Setter(Getter().SetCol3(v)));
            }
            set
            {
                Setter(Getter().SetCol3(value.ToVector2()));
            }
        }

        public Matrix3 ToMatrix3()
        {
            return new Matrix3(ToArray());
        }
    }
}